package org.ala.tiktools.rocketmq.spring;

import com.google.common.collect.Sets;
import org.ala.tiktools.logs.LoggerFactory;
import org.ala.tiktools.rocketmq.SnowflakeIdGenerator;
import org.ala.tiktools.rocketmq.annotations.ProducerService;
import org.ala.tiktools.rocketmq.config.ConfigInfo;
import org.ala.tiktools.rocketmq.producer.ProducerServiceFactoryBean;
import org.ala.tiktools.rocketmq.producer.RocketMQProducerInitializer;
import org.slf4j.Logger;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.*;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.AbstractClassTestingTypeFilter;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.HashSet;
import java.util.Set;


/**
 * @author ala
 * @date 2024-11-29 13:28
 */
public class RocketMQBeanRegistyPostProcesser implements BeanDefinitionRegistryPostProcessor, EnvironmentAware, ResourceLoaderAware {


    static Logger log = LoggerFactory.getLogger("rocketmq", "init");


    protected Environment env;
    protected ResourceLoader resourceLoader;
    protected BeanDefinitionRegistry beanDefinitionRegistry;

    /**
     *  ProducerService注册器
     */
    protected RocketMQProducerInitializer producerInitializer;

    @Override
    public void setEnvironment(Environment environment) {
        env = environment;

        //  解析配置文件
        ConfigInfo.INSTANCE = ConfigInfo.build(env);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
    }
    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        this.beanDefinitionRegistry = beanDefinitionRegistry;

        //  解析配置
        if (ConfigInfo.INSTANCE == null) {
            ConfigInfo.INSTANCE = ConfigInfo.build(env);
        }

        //  初始化雪花id生成器
        initSnowFlake(beanDefinitionRegistry);

        //  初始化Producer代理，每个ProducerService注解接口的每个ProducerMethod方法会生成一个producer实例
        initProducerServices();
    }
    /**
     *  初始化雪花id生成器
     */
    protected void initSnowFlake(BeanDefinitionRegistry beanDefinitionRegistry) {
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(SnowflakeIdGenerator.class, () -> {
            return SnowflakeIdGenerator.build(ConfigInfo.INSTANCE.getSnowflow());
        });

        AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
        beanDefinition.setPrimary(true);
        //	注册
        BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, "RocketMQSnowflakeIdGenerator");
        BeanDefinitionReaderUtils.registerBeanDefinition(holder, beanDefinitionRegistry);
    }

    /**
     *  初始化Producer代理，每个ProducerService注解接口的每个ProducerMethod方法会生成一个producer实例
     */
    protected void initProducerServices() {
        ClassPathScanningCandidateComponentProvider scanner = createScanner(env, resourceLoader);
        //  要扫描的包目录（整体扫描会有问题，会扫描所有的jar包。慢不说，还有可能扫描到其他依赖杂七杂八的类）
        String[] pkgs = ConfigInfo.INSTANCE.getProducerPackages();
        for (String pkg : pkgs) {
            if (StringUtils.isEmpty(pkg)) {continue;}
            Set<BeanDefinition> producerServiceBeanDefinitions = scanner.findCandidateComponents(pkg);
            producerServiceBeanDefinitions.forEach(this::initProducerService);
        }
    }
    /**
     *  初始化ProducerService
     */
    protected void initProducerService(BeanDefinition bd) {
        String className = bd.getBeanClassName();
        Class<?> producerServiceClass = null;
        try {
            producerServiceClass = ClassUtils.forName(className, this.getClass().getClassLoader());
        } catch (ClassNotFoundException e) {
            log.error("[RocketMQBeanRegistyPostProcesser initProducerService] 加载producerService注解类型失败. class:" + className, e);
        }

        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(ProducerServiceFactoryBean.class);
        builder.addPropertyValue("type", producerServiceClass);
        builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);

        //	生成beanDefintion
        AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
        beanDefinition.setPrimary(true);
        //	注册
        BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, bd.getBeanClassName());
        BeanDefinitionReaderUtils.registerBeanDefinition(holder, beanDefinitionRegistry);
    }

    /**
     * 初始化扫描器
     */
    protected ClassPathScanningCandidateComponentProvider createScanner(Environment env, ResourceLoader resourceLoader) {
        ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider() {
            @Override
            protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
                if (beanDefinition.getMetadata().isIndependent()) {
                    if (
                            beanDefinition.getMetadata().isInterface()
                                    && beanDefinition.getMetadata().getInterfaceNames().length == 1
                                    && Annotation.class.getName().equals(beanDefinition.getMetadata().getInterfaceNames()[0])
                    ) {
                        try {
                            Class<?> target = ClassUtils.forName(beanDefinition.getMetadata().getClassName(), this.getClass().getClassLoader());
                            return !target.isAnnotation();
                        } catch (ClassNotFoundException | LinkageError e) {
//                            this.logger.warn("[RocketMQBeanRegistyPostProcesser createScanner] 加载类型错误:" + beanDefinition.getMetadata().getClassName(), e);
                        }
                    }
                    return true;
                }
                return false;
            }
        };

        scanner.setEnvironment(env);
        scanner.setResourceLoader(resourceLoader);

        //  要扫描的注解类型
        //	DelayMessageClient注解过滤器
        AnnotationTypeFilter annotationFilter = new AnnotationTypeFilter(ProducerService.class);
        scanner.addIncludeFilter(annotationFilter);
        //	给scanner注册annotation过滤器和内部类过滤器
//        AbstractClassTestingTypeFilter filter = new AbstractClassTestingTypeFilter() {
//            @Override
//            protected boolean match(ClassMetadata metadata) {
//                //	内部类的$转换为.
//                String className = metadata.getClassName().replaceAll("\\$", ".");
//                return clientClasses.contains(className);
//            }
//        };
//        scanner.addIncludeFilter(new MultiTypeFilter(new TypeFilter[] {filter, annotationFilter}));

        return scanner;
    }


    /**
     * 多filter
     */
    protected static class MultiTypeFilter implements TypeFilter {
        protected TypeFilter[] filters;
        public MultiTypeFilter(TypeFilter[] filters) {
            super();
            this.filters = filters;
        }
        @Override
        public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
            for (TypeFilter filter : filters) {
                //	只要有1个条件不满足则判定为false
                if (!filter.match(metadataReader, metadataReaderFactory)) return false;
            }
            return true;
        }
    }

}
